package com.pzi.blog.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.pzi.blog.dao.Comments;
import com.pzi.blog.dao.mapper.CommentsMapper;
import com.pzi.blog.service.CommentsService;
import com.pzi.blog.vo.CommentsVo;
import com.pzi.blog.vo.Result;
import com.pzi.blog.vo.ReplyCommentsVo;
import com.pzi.blog.vo.params.CommentsParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;

/**
 * @author Pzi
 * @create 2022-04-18 0:40
 */
@Service
@Slf4j
public class CommentsServiceImpl implements CommentsService {

    @Autowired
    private CommentsMapper commentsMapper;

    @Override
    public Result selectCommentsByArticleId(Long articleId) {

        LambdaQueryWrapper<Comments> lqw = new LambdaQueryWrapper<>();
        lqw.eq(Comments::getArticleId,articleId);
//        select * from ms_comments where article_id = ?
//        把这篇文章下的所有的评论都查了出来
        List<Comments> comments = commentsMapper.selectList(lqw);
//        要进行筛选，将顶级评论与子评论封装
        List<CommentsVo> commentsVos = copyToVoList(comments);
        return Result.success(commentsVos);

    }

    /**
     *
     * @param commentsParam 表单中传递过来的请求参数
     * @return
     */
    @Override
    public Result insert(CommentsParam commentsParam) {

        Comments comments = new Comments();
        BeanUtils.copyProperties(commentsParam,comments);
        comments.setReplyCount(0l);
        comments.setCommentTime(System.currentTimeMillis());
        comments.setArticleId(Long.valueOf(commentsParam.getArticleId()));
        int insert = commentsMapper.insert(comments);
        log.warn("insert = " + insert);

        //  如果replyId不等于0，说明该评论是子评论/孙子评论。
        //  那么要为该子评论对应的顶级评论重新赋值 replyCount
        if (commentsParam.getReplyId() != 0l){
            //  通过顶级评论的replyId属性，查询出它对应的顶级评论
            LambdaQueryWrapper<Comments> lqw = new LambdaQueryWrapper<>();
            lqw.eq(Comments::getId,commentsParam.getReplyId());
            Comments c = commentsMapper.selectOne(lqw);

            //  查询这个顶级评论它下面有几条replyComment
            LambdaQueryWrapper<Comments> lqw2 = new LambdaQueryWrapper<>();
            lqw2.eq(Comments::getReplyId,c.getId());

            log.warn("查询顶级评论的评论数目了...");
            log.warn("!!!!!!!!!!!!!!!");
            log.warn("!!!!!!!!!!!!!!!");
            //  SELECT COUNT(*) FROM ms_comments WHERE ms_comments.reply_id = ?
            Integer replyCounts = commentsMapper.selectCount(lqw2);

            log.warn("设置replyCounts语句");
            //  为顶级评论的replyCounts赋值
            LambdaQueryWrapper<Comments> lqw3 = new LambdaQueryWrapper<>();
            lqw3.eq(Comments::getId,c.getId());
            Comments setComment = new Comments();
            setComment.setReplyCount(Long.valueOf(replyCounts));
            commentsMapper.update(setComment,lqw3);
        }

        Long id = comments.getId();
        HashMap<String, Long> data = new HashMap<>();
        data.put("commentId",id);
        return Result.success(data);
    }

    private List<CommentsVo> copyToVoList(List<Comments> comments) {

        ArrayList<CommentsVo> commentsVoList = new ArrayList<>();
        for (Comments c : comments){

            // 1.如果是顶级评论，则将它转换成Vo类。顶级评论才会被加载到Vo中，避免非顶级评论被显示到了顶级评论的区域的问题
            // 判断是否是顶级评论的条件：
            if (c.getReplyCount() >= 0 && c.getReplyId()==0 && c.getParentId()==0){
                CommentsVo commentsVo = copyToVo(c);
                commentsVoList.add(commentsVo);
            }
        }
        return commentsVoList;
    }

//    将每一个comments ==> commentsVo
    private CommentsVo copyToVo(Comments comments) {

        CommentsVo commentsVo = new CommentsVo();
        BeanUtils.copyProperties(comments,commentsVo);
        commentsVo.setCommentTime(new DateTime(comments.getCommentTime()).toString("yyyy-MM-dd HH:mm"));

        //  查询该文章的评论数量
        LambdaQueryWrapper<Comments> lqw = new LambdaQueryWrapper<>();
        lqw.eq(Comments::getArticleId,comments.getArticleId());
        log.warn("!!!!!!!!!!!!!!!!!!!!!!!!");
        log.warn("!!!!!!!!!!!!!!!!!!!!!!!!");
        log.warn("!!!!!!!!!!!!!!!!!!!!!!!!");
        Integer integer = commentsMapper.selectCount(lqw);
        commentsVo.setCommentTotalCounts(integer);

        // 2.为顶级评论赋值上它的所有子评论
        commentsVo.setReplyComments(findReplyComment(comments));
        return commentsVo;
    }

//    找某个顶级评论下面的所有子评论
    private List<ReplyCommentsVo> findReplyComment(Comments comments){
        // 1.评论的文章是同一个，articleId、replyId要相同，parentId可能不同
        LambdaQueryWrapper<Comments> lqw = new LambdaQueryWrapper<>();
        lqw.eq(Comments::getReplyId,comments.getId());

//        select * from ms_comments where reply_id = ?
        List<Comments> replyCommentsList = commentsMapper.selectList(lqw);

//        将所有子评论 ==> 子评论的Vo类型
        List<ReplyCommentsVo> replyCommentsVos = copyToReplyVoList(replyCommentsList);

        return replyCommentsVos;
    }

    private List<ReplyCommentsVo> copyToReplyVoList(List<Comments> replyCommentsList) {
        ArrayList<ReplyCommentsVo> replyCommentsVoList = new ArrayList<>();
        for (Comments c : replyCommentsList){
            ReplyCommentsVo replyCommentsVo = copyToReplyVo(c);
            replyCommentsVoList.add(replyCommentsVo);
        }
        return replyCommentsVoList;
    }


    private ReplyCommentsVo copyToReplyVo(Comments c) {
        ReplyCommentsVo replyCommentsVo = new ReplyCommentsVo();
        BeanUtils.copyProperties(c,replyCommentsVo);
        replyCommentsVo.setCommentTime(new DateTime(c.getCommentTime()).toString("yyyy-MM-dd HH:mm"));

//        根据c.parentId，查询出parentnickName
        LambdaQueryWrapper<Comments> lqw = new LambdaQueryWrapper<>();
        lqw.eq(Comments::getId,c.getParentId());
        log.warn("查询子评论的父评论中.......");
        Comments comments = commentsMapper.selectOne(lqw);
        replyCommentsVo.setParentNickName(comments.getNickName());
        return replyCommentsVo;
    }

}
